@file:Suppress("unused")

package com.zxf.basic.expand

import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import java.io.*
import java.security.MessageDigest
import java.security.NoSuchAlgorithmException
import java.util.regex.Pattern
import java.util.regex.PatternSyntaxException


const val BLANK_UTF8_DEF = "%20"
const val BLANK_INDEX = 32
const val CN_RANGE_MIN = 19968 // \u4e00
const val CN_RANGE_MAX = 171941 // \u9fa5
const val HEX_CODE = "0123456789ABCDEF"

/**
 * 将String中的字符全角化。即将所有的数字、字母及标点全部转为全角字符，使它们与汉字同占两个字节
 */
fun String.toDBC(): String {
    val c = toCharArray()
    for (i in c.indices) {
        if (c[i].toInt() == 12288) {
            c[i] = 32.toChar()
            continue
        }
        if (c[i].toInt() in 65281..65374) {
            c[i] = (c[i].toInt() - 65248).toChar()
        }
    }
    return String(c)
}

/**
 * 去除特殊字符或将所有中文标号替换为英文标号
 */
@Throws(PatternSyntaxException::class)
fun String.toEnSymbol(): String {
    val s = replace("【".toRegex(), "[").replace("】".toRegex(), "]").replace("！".toRegex(), "!") // 替换中文标号
    val regEx = "[『』]" // 清除掉特殊字符
    val p = Pattern.compile(regEx)
    val m = p.matcher(s)
    return m.replaceAll("").trim()
}

fun CharSequence?.isEmpty(): Boolean {
    return isNullOrEmpty()
}

fun CharSequence?.isNotEmpty(): Boolean {
    return !isNullOrEmpty()
}

fun CharSequence?.copyToClipboard(context: Context) {
    val cm = context.systemService<ClipboardManager>()
    cm.setPrimaryClip(ClipData.newPlainText(null, this))
}

/**
 * 根据字体大小及限制的PX长度来截取字符串
 *
 * @param textSize 字体像素大小
 * @param pxLength 像素长度限制
 * @param symbol   超时长度限制时追加的标识
 * @return 截取后的字符串
 */
fun CharSequence.cut(textSize: Float, pxLength: Float, symbol: String): String {
    val halfCharLen = textSize / 2

    var curLen = 0
    var count = 0
    for (i in 0 until length) {
        val chr1 = this[i].toInt()
        curLen += if (chr1 in CN_RANGE_MIN..CN_RANGE_MAX) {
            // CN
            textSize.toInt()
        } else {
            halfCharLen.toInt()
        }

        if (curLen > pxLength) {
            break
        }

        count++
    }

    val sb = StringBuffer()
            .append(subSequence(0, count))

    if (curLen > pxLength && symbol.isNotEmpty()) {
        sb.append(symbol)
    }

    return sb.toString()
}

/**
 * 过滤空串
 */
fun String?.filterNull(): String {
    return this ?: ""
}

/**
 * 把url的中文转换url格式
 */
fun String.toUtf8(): String {
    val sb = StringBuffer()
    (0 until length)
            .asSequence()
            .map { this[it] }
            .forEach {
                if (it.toInt() in 0..255) {
                    // 非中文
                    if (it.toInt() == BLANK_INDEX) {
                        /**
                         * 空格需要特殊处理
                         * PS: 不能使用[java.net.URLEncoder.encode]处理，会变成'+'，浏览器无法辨识
                         */
                        sb.append(BLANK_UTF8_DEF)
                    } else {
                        sb.append(it)
                    }
                } else {

                    val bytes: ByteArray = try {
                        it.toString().toByteArray()
                    } catch (ex: Exception) {
                        ByteArray(0)
                    }

                    bytes.forEach {
                        var i: Int = it.toInt()
                        if (it < 0) i += 256
                        sb.append("%" + Integer.toHexString(i).toUpperCase())
                    }

//                        for (j in b.indices) {
//                            var k = b[j].toInt()
//                            if (k < 0) {
//                                k += 256
//                            }
//                            sb.append("%" + Integer.toHexString(k).toUpperCase())
//                        }
                }
            }
    return sb.toString()
}

/**
 * 首字母大写
 */
fun String.capitalize(): String {
    val cs = toCharArray()
    cs[0] = cs[0] - 32
    return String(cs)
}

/**
 * String转InputStream
 */
@Throws(Exception::class)
fun String.toInputStream(): InputStream {
    return ByteArrayInputStream(toByteArray(charset("ISO-8859-1")))
}

/**
 * 16进制转10进制
 *
 * @param hex
 * @return
 */
//    fun toString(hex: String): String? {
//        val hexs = hex.toCharArray()
//        val bytes = ByteArray(hex.length / 2)
//        var network: Int
//        for (i in bytes.indices) {
//            HEX_CODE.indexOf()
//            network = HEX_CODE.indexOf(hexs[2 * i].toInt()) * 16
//            network += HEX_CODE.indexOf(hexs[2 * i + 1].toInt())
//            bytes[i] = (network and 0xff).toByte()
//        }
//        return String(bytes)
//    }


/**
 * 10进制转16进制
 *
 * @param str
 * @return
 */
//    fun toHex(str: String): String {
//        val chars = HEX_CODE.toCharArray()
//        val sb = StringBuilder("")
//        val bs = str.toByteArray()
//        var bit: Int
//        for (i in bs.indices) {
//            bit = bs[i] and 0x0f0 shr 4
//            sb.append(chars[bit])
//            bit = bs[i] and 0x0f
//            sb.append(chars[bit])
//        }
//        return sb.toString()
//    }

fun String.md5(): String {
    return try {
        //获取md5加密对象
        val instance: MessageDigest = MessageDigest.getInstance("MD5")
        //对字符串加密，返回字节数组
        val digest: ByteArray = instance.digest(toByteArray())
        val sb: StringBuffer = StringBuffer()
        for (b in digest) {
            //获取低八位有效值
            val i: Int = b.toInt() and 0xff
            //将整数转化为16进制
            var hexString = Integer.toHexString(i)
            if (hexString.length < 2) {
                //如果是一位的话，补0
                hexString = "0$hexString"
            }
            sb.append(hexString)
        }
        return sb.toString()

    } catch (e: NoSuchAlgorithmException) {
        ""
    }
}

/**
 * 获取文件后缀名
 */
val String?.suffix: String
    get() {
        if (this != null && isNotEmpty()) {
            val fileSuffix = substringAfterLast('.', "")
            if (fileSuffix.isNotEmpty() && fileSuffix.matches(Regex("([a-z]|[A-Z])*"))) {
                return fileSuffix
            }
        }
        return ""
    }

/**
 * 保存字符串到txt文件中
 */
fun String.saveStringToTxt(filePath: String?, fileName: String, saveSuccess: (savePath: String) -> Unit, saveFailed: (errorMsg: String) -> Unit) {
    if (fileName.suffix.toLowerCase() != "txt") {
        saveFailed.invoke("this file is not a txt file")
        return
    }
    runOnSubThread {
        val file = File(filePath)
        if (!file.exists()) file.mkdirs()
        val txtFilePath = filePath.plus("/").plus(fileName)
        val txtFile = File(txtFilePath)
        if (txtFile.exists()) txtFile.createNewFile()
        var os: FileOutputStream? = null
        try {
            os = FileOutputStream(txtFile)
            os.write(toByteArray())
            runOnMainThread {
                saveSuccess.invoke(txtFilePath)
            }
        } catch (e: Exception) {
            runOnMainThread {
                saveFailed.invoke(e.toString())
            }
        } finally {
            if (os != null) {
                try {
                    os.close()
                } catch (e: IOException) {
                }
            }
        }
    }
}

fun String.isLocalPath(): Boolean {
    return isFileUri() || isContentUri()
}

fun String.isFileUri(): Boolean {
    return startsWith("file://")
}

fun String.isContentUri(): Boolean {
    return startsWith("content://")
}

fun String.replaceLineBreak(): String = this.replace("\n", "")
